<template>
  <el-dialog :title="title" :visible.sync="open" width="1300px">
    <el-row>

      <!-- 产品绑定 -->
      <el-col :span="8">
        <el-table
          ref="productTable"
          :data="productList"
          max-height="450"
          highlight-current-row
          @current-change="handleProductCurrentChangeEvent"
          style="height: 600px"
        >

          <el-table-column label="产品名称" align="center" prop="productName"/>

          <el-table-column label="属性" width="110px" align="center">
            <template slot-scope="scope">
              <el-checkbox v-model="scope.row.propertyChecked" @change="handleCheckProductPropertyBoxChangeEvent(scope.row)"/>
            </template>
          </el-table-column>

          <el-table-column label="功能" width="110px" align="center">
            <template slot-scope="scope">
              <el-checkbox v-model="scope.row.functionChecked" @change="handleCheckProductFunctionBoxChangeEvent(scope.row)"/>
            </template>
          </el-table-column>

        </el-table>
      </el-col>

      <!-- 设备绑定 -->
      <el-col :span="8">
        <div style="margin-left: 20px">
          <el-table
            ref="deviceTable"
            :data="deviceList"
            highlight-current-row
            max-height="450"
            @current-change="handleDeviceCurrentChangeEvent"
            style="height: 600px"
          >
            <el-table-column label="设备名称" align="center" prop="deviceName"/>
            <el-table-column
              width="110px"
              align="center"
              label-class-name="label-properties"
              :render-header="handleDevicePropertiesRenderHeader"
            >
              <template slot-scope="scope">
                <el-checkbox
                  v-model="scope.row.propertyChecked"
                  @change="handleCheckDevicePropertyBoxChangeEvent(scope.row)"
                  :disabled="!scope.row.haveProperty"
                />
              </template>
            </el-table-column>
            <el-table-column
              width="110px"
              align="center"
              label-class-name="label-functions"
              :render-header="handleDeviceFunctionsRenderHeader"
            >
              <template slot-scope="scope">
                <el-checkbox
                  v-model="scope.row.functionChecked"
                  :disabled="!scope.row.haveFunction"
                  @change="handleCheckDeviceFunctionBoxChangeEvent(scope.row)"
                />
              </template>
            </el-table-column>
          </el-table>
        </div>
      </el-col>

      <!-- 属性和功能绑定 -->
      <el-col :span="8">
        <div style="margin-left: 20px">
          <!-- 物模型标签页 -->
          <el-tabs v-model="activeName" type="card">
            <!-- 属性 -->
            <el-tab-pane label="属性" name="properties">

              <!-- 属性列表 -->
              <el-table :data="properties" max-height="450">
                <el-table-column align="center" :render-header="handlePhysicalModelPropertiesRenderHeader">
                  <template slot-scope="scope">
                    <el-checkbox v-model="scope.row.propertyChecked" @change="handleCheckPhysicalModelPropertyBoxChangeEvent(scope.row)"/>
                  </template>
                </el-table-column>
                <el-table-column label="属性标识" align="center" prop="id"/>
                <el-table-column label="属性名称" align="center" prop="name"/>
              </el-table>

            </el-tab-pane>

            <!-- 功能 -->
            <el-tab-pane label="功能" name="functions">

              <!-- 功能列表 -->
              <el-table :data="functions" max-height="450">
                <el-table-column align="center" :render-header="handlePhysicalModelFunctionsRenderHeader">
                  <template slot-scope="scope">
                    <el-checkbox v-model="scope.row.functionChecked" @change="handleCheckPhysicalModelFunctionBoxChangeEvent(scope.row)"/>
                  </template>
                </el-table-column>
                <el-table-column label="功能标识" align="center" prop="id"/>
                <el-table-column label="功能名称" align="center" prop="name"/>
              </el-table>

            </el-tab-pane>
          </el-tabs>
        </div>
      </el-col>
    </el-row>

    <div slot="footer" class="dialog-footer">
      <el-button @click="cancel">取 消</el-button>
      <el-button type="primary" @click="submitForm">确 定</el-button>
    </div>

  </el-dialog>
</template>

<script>
import { queryProduct } from '@/api/iot/product'
import { getDeviceCache } from '@/api/iot/device'
import { bind } from '@/api/rule-engine/job'

export default {
  name: 'JobBindDevice',
  data() {
    return {
      // 弹出层标题
      title: '设备绑定',
      // 是否显示弹出层
      open: false,
      // 调度任务id
      jobId: undefined,
      // 调用目标字符串
      invokeTarget: {
        properties: {},
        functions: {},
      },
      // 产品表格数据
      productList: [],
      // 设备表格数据
      deviceList: [],
      // 属性表格数据
      properties: [],
      // 功能表格数据
      functions: [],
      // 物模型tabs，默认展示属性定义
      activeName: 'properties',

      // 设备属性表头复选框选中状态
      isCheckDeviceProperties: false,
      // 设备功能表头复选框选中状态
      isCheckDeviceFunctions: false,
      // 物模型属性表头复选框选中状态
      isCheckPhysicalModelProperties: false,
      // 物模型功能表头复选框选中状态
      isCheckPhysicalModelFunctions: false,

      // 设备属性表头复选框部分选中状态
      indeterminateDeviceProperties: false,
      // 设备功能表头复选框部分选中状态
      indeterminateDeviceFunctions: false,
      // 物模型属性表头复选框部分选中状态
      indeterminatePhysicalModelProperties: false,
      // 物模型功能表头复选框部分选中状态
      indeterminatePhysicalModelFunctions: false,

      // 当前选中的产品
      currentSelectedProduct: undefined,
      // 当前选中的设备
      currentSelectedDevice: undefined,

      // 设备属性复选框是否禁用（表头）
      isDevicePropertiesCheckBoxDisabled: false,
      // 设备功能复选框是否禁用（表头）
      isDeviceFunctionsCheckBoxDisabled: false,
      // 物模型属性复选框是否禁用（表头）
      isPhysicalModelPropertiesCheckBoxDisabled: false,
      // 物模型功能复选框是否禁用（表头）
      isPhysicalModelFunctionsCheckBoxDisabled: false,

      selectProductExecutionCallback: false
    }
  },
  computed: {
    /** 当前是否有选中的设备属性 */
    isCurrentDevicePropertiesHaveChecked() {
      return this.isCheckDeviceProperties || this.indeterminateDeviceProperties
    },
    /** 当前是否有选中的设备功能 */
    isCurrentDeviceFunctionsHaveChecked() {
      return this.isCheckDeviceFunctions || this.indeterminateDeviceFunctions
    },
    /** 当前是否有选中的物模型属性 */
    isCurrentPhysicalModelPropertiesHaveChecked() {
      return this.isCheckPhysicalModelProperties || this.indeterminatePhysicalModelProperties
    },
    /** 当前是否有选中的物模型功能 */
    isCurrentPhysicalModelFunctionsHaveChecked() {
      return this.isCheckPhysicalModelFunctions || this.indeterminatePhysicalModelFunctions
    },
  },
  watch: {
    async open(visible) {
      if (visible) {
        await this.getProducts()
        // 还原选中的产品属性
        this.restoreCheckedProductProperties()
        // 还原选中的产品功能
        this.restoreCheckedProductFunctions()
        // 选中产品表格第一行
        this.setProductCurrentRow(this.productList[0])
      } else {
        this.reset()
      }
    },

    /** 当前是否有选中的设备属性 */
    isCurrentDevicePropertiesHaveChecked(state) {
      // 更新所属产品选中状态
      this.$set(this.currentSelectedProduct, 'propertyChecked', state)
      // 更新产品属性绑定数据
      this.updateProductPropertiesInvokeTarget(this.currentSelectedProduct.id, state)
    },

    /** 当前是否有选中的设备功能 */
    isCurrentDeviceFunctionsHaveChecked(state) {
      // 更新所属产品选中状态
      this.$set(this.currentSelectedProduct, 'functionChecked', state)
      // 更新产品功能绑定数据
      this.updateProductFunctionsInvokeTarget(this.currentSelectedProduct.id, state)
    },

    /** 当前是否有选中的物模型属性 */
    isCurrentPhysicalModelPropertiesHaveChecked(state) {
      // 更新所属设备选中状态
      this.$set(this.currentSelectedDevice, 'propertyChecked', state)
      // 更新设备属性复选框状态（表头）
      this.updateDevicePropertiesCheckboxState()
      // 更新设备属性绑定数据
      this.updateDevicePropertiesInvokeTarget(this.currentSelectedProduct.id, this.currentSelectedDevice.id, state)
    },

    /** 当前是否有选中的物模型功能 */
    isCurrentPhysicalModelFunctionsHaveChecked(state) {
      // 更新所属设备选中状态
      this.$set(this.currentSelectedDevice, 'functionChecked', state)
      // 更新设备功能复选框状态（表头）
      this.updateDeviceFunctionsCheckboxState()
      // 更新设备功能绑定数据
      this.updateDeviceFunctionsInvokeTarget(this.currentSelectedProduct.id, this.currentSelectedDevice.id, state)
    },

  },
  methods: {
    /** 取消按钮 */
    cancel() {
      this.open = false
    },
    /** 表格数据重置 */
    reset() {
      this.productList = []
      this.deviceList = []
      this.properties = []
      this.functions = []
      this.invokeTarget = {
        properties: {},
        functions: {},
      }

      // 调度任务id
      this.jobId = undefined

      // 设备属性表头复选框选中状态
      this.isCheckDeviceProperties = false
      // 设备功能表头复选框选中状态
      this.isCheckDeviceFunctions = false

      // 设备属性表头复选框部分选中状态
      this.indeterminateDeviceProperties = false
      // 设备功能表头复选框部分选中状态
      this.indeterminateDeviceFunctions = false

      // 设备属性复选框是否禁用（表头）
      this.isDevicePropertiesCheckBoxDisabled = false
      // 设备功能复选框是否禁用（表头）
      this.isDeviceFunctionsCheckBoxDisabled = false
    },

    /** 获取产品信息 */
    getProducts() {
      return queryProduct({ publishState: 1}).then(({ data }) => {
        this.productList = data || []
      })
    },

    /** 获取设备信息 */
    getDevices(productId) {
      this.properties = []
      this.functions = []
      return getDeviceCache(productId).then(({ data }) => {
        // 设备物模型解析转换
        this.deriveMetadataParseConvert(data)
        this.deviceList = data || []
      })
    },

    /** 绑定按钮操作 */
    handBind(jobId, invokeTarget) {
      this.reset()
      this.jobId = jobId
      this.open = true
      if (invokeTarget) {
        this.invokeTarget = JSON.parse(invokeTarget)
      }
    },

    /** 确定按钮 **/
    submitForm() {
      bind(this.jobId, JSON.stringify(this.invokeTarget)).then(() => {
        this.$modal.msgSuccess('绑定成功')
        this.cancel()
        this.$emit('submit')
      })
    },

    /** 设备物模型解析转换 */
    deriveMetadataParseConvert(data = []) {
      data.forEach(device => {
        const deriveMetadata = JSON.parse(device.deriveMetadata)
        device.deriveMetadata = deriveMetadata
        device.haveProperty = deriveMetadata.properties.length > 0
        device.haveFunction = deriveMetadata.functions.length > 0
      })
    },

    /********************************* 复选框（表头） ***************************************/

    /** 设备属性表头复选框 */
    handleDevicePropertiesRenderHeader(h) {
      return h('span', [
        h('el-checkbox', {
          on: {
            change: this.handleCheckDevicePropertiesBoxChangeEvent
          },
          props: {
            value: this.isCheckDeviceProperties,
            indeterminate: this.indeterminateDeviceProperties,
            disabled: this.isDevicePropertiesCheckBoxDisabled
          }
        })
      ])
    },

    /** 设备功能表头复选框 */
    handleDeviceFunctionsRenderHeader(h) {
      return h('span', [
        h('el-checkbox', {
          on: {
            change: this.handleCheckDeviceFunctionsBoxChangeEvent
          },
          props: {
            value: this.isCheckDeviceFunctions,
            indeterminate: this.indeterminateDeviceFunctions,
            disabled: this.isDeviceFunctionsCheckBoxDisabled
          }
        })
      ])
    },

    /** 物模型属性表头复选框 */
    handlePhysicalModelPropertiesRenderHeader(h) {
      return h('span', [
        h('el-checkbox', {
          on: {
            change: this.handleCheckPhysicalModelPropertiesBoxChangeEvent
          },
          props: {
            value: this.isCheckPhysicalModelProperties,
            indeterminate: this.indeterminatePhysicalModelProperties,
            disabled: this.isPhysicalModelPropertiesCheckBoxDisabled
          }
        })
      ])
    },

    /** 物模型功能表头复选框 */
    handlePhysicalModelFunctionsRenderHeader(h) {
      return h('span', [
        h('el-checkbox', {
          on: {
            change: this.handleCheckPhysicalModelFunctionsBoxChangeEvent
          },
          props: {
            value: this.isCheckPhysicalModelFunctions,
            indeterminate: this.indeterminatePhysicalModelFunctions,
            disabled: this.isPhysicalModelFunctionsCheckBoxDisabled
          }
        })
      ])
    },

    /** 设备属性表头复选框选择变化事件处理 */
    handleCheckDevicePropertiesBoxChangeEvent(checked) {
      let selectedQuantity = 0
      this.deviceList.forEach(device => {
        if (device.haveProperty) {
          this.$set(device, 'propertyChecked', checked)
          if (checked) {
            selectedQuantity ++
          }
          // 更新设备属性绑定数据
          this.updateDevicePropertiesInvokeTarget(device.productId, device.id, checked, device.deriveMetadata)
          // 更新选中的的设备物模型属性
          if (device.id === this.currentSelectedDevice.id) {
            this.checkAllPhysicalModelProperties(checked)
          }
        }
      })

      if (selectedQuantity > 0 && selectedQuantity < this.deviceList.length) {
        this.indeterminateDeviceProperties = true
        this.isCheckDeviceProperties = false
      }else {
        this.isCheckDeviceProperties = checked
        this.indeterminateDeviceProperties = false
      }
    },

    /** 设备功能表头复选框选择变化事件处理 */
    handleCheckDeviceFunctionsBoxChangeEvent(checked) {
      let selectedQuantity = 0
      this.deviceList.forEach(device => {
        if (device.haveFunction) {
          this.$set(device, 'functionChecked', checked)
          if (checked) {
            selectedQuantity ++
          }
          // 更新设备功能绑定数据
          this.updateDeviceFunctionsInvokeTarget(device.productId, device.id, checked, device.deriveMetadata)
          // 更新选中的的设备物模型功能
          if (device.id === this.currentSelectedDevice.id) {
            this.checkAllPhysicalModelFunctions(checked)
          }
        }
      })

      if (selectedQuantity > 0 && selectedQuantity < this.deviceList.length) {
        this.indeterminateDeviceFunctions = true
        this.isCheckDeviceFunctions = false
      }else {
        this.isCheckDeviceFunctions = checked
        this.indeterminateDeviceFunctions = false
      }
    },

    /** 物模型属性表头复选框选择变化事件处理 */
    handleCheckPhysicalModelPropertiesBoxChangeEvent(checked) {
      this.isCheckPhysicalModelProperties = checked
      this.indeterminatePhysicalModelProperties = false

      this.properties.forEach(property => {
        this.$set(property, 'propertyChecked', checked)

        const productId = this.currentSelectedProduct.id
        const deviceId = this.currentSelectedDevice.id
        // 更新物模型属性绑定数据
        this.updatePhysicalModelPropertiesInvokeTarget(productId, deviceId, property.id, checked)
      })
    },

    /** 物模型功能表头复选框选择变化事件处理 */
    handleCheckPhysicalModelFunctionsBoxChangeEvent(checked) {
      this.isCheckPhysicalModelFunctions = checked
      this.indeterminatePhysicalModelFunctions = false

      this.functions.forEach(fun => {
        this.$set(fun, 'functionChecked', checked)

        const productId = this.currentSelectedProduct.id
        const deviceId = this.currentSelectedDevice.id
        // 更新物模型属性绑定数据
        this.updatePhysicalModelFunctionsInvokeTarget(productId, deviceId, fun.id, checked)
      })
    },

    /** 更新设备属性复选框状态（表头） */
    updateDevicePropertiesCheckboxState() {
      const count = this.deviceList.length

      if (count <= 0) {
        this.isDevicePropertiesCheckBoxDisabled = true
        this.indeterminateDeviceProperties = false
        this.isCheckDeviceProperties = false
        return
      }

      let selectedQuantity = this.deviceList.filter(obj => obj.propertyChecked === true).length

      // 没有选中的复选框则取消选中表头属性复选框
      if (selectedQuantity === 0) {
        this.isDevicePropertiesCheckBoxDisabled = false
        this.isCheckDeviceProperties = false
        this.indeterminateDeviceProperties = false
        return
      }

      // 总数量等于选中的数据则选中表头属性复选框
      if (count === selectedQuantity) {
        this.isDevicePropertiesCheckBoxDisabled = false
        this.isCheckDeviceProperties = true
        this.indeterminateDeviceProperties = false
        return
      }

      this.isDevicePropertiesCheckBoxDisabled = false
      this.indeterminateDeviceProperties = true
      this.isCheckDeviceProperties = false

    },

    /** 更新设备功能复选框状态（表头） */
    updateDeviceFunctionsCheckboxState() {
      const count = this.deviceList.length

      if (count <= 0) {
        this.isDeviceFunctionsCheckBoxDisabled = true
        this.indeterminateDeviceFunctions = false
        this.isCheckDeviceFunctions = false
        return
      }

      let selectedQuantity = this.deviceList.filter(obj => obj.functionChecked === true).length

      // 没有选中的复选框则取消选中表头功能复选框
      if (selectedQuantity === 0) {
        this.isDeviceFunctionsCheckBoxDisabled = false
        this.isCheckDeviceFunctions = false
        this.indeterminateDeviceFunctions = false
        return
      }

      // 总数量等于选中的数据则选中表头功能复选框
      if (count === selectedQuantity) {
        this.isDeviceFunctionsCheckBoxDisabled = false
        this.isCheckDeviceFunctions = true
        this.indeterminateDeviceFunctions = false
        return
      }

      this.isDeviceFunctionsCheckBoxDisabled = false
      this.indeterminateDeviceFunctions = true
      this.isCheckDeviceFunctions = false
    },

    /** 更新物模型属性复选框状态（表头） */
    updatePhysicalModelPropertiesCheckboxState() {
      const count = this.properties.length

      if (count <= 0) {
        this.isPhysicalModelPropertiesCheckBoxDisabled = true
        this.indeterminatePhysicalModelProperties = false
        this.isCheckPhysicalModelProperties = false
        return
      }

      let selectedQuantity = this.properties.filter(obj => obj.propertyChecked === true).length

      // 没有选中的复选框则取消选中表头属性复选框
      if (selectedQuantity === 0) {
        this.isPhysicalModelPropertiesCheckBoxDisabled = false
        this.isCheckPhysicalModelProperties = false
        this.indeterminatePhysicalModelProperties = false
        return
      }

      // 总数量等于选中的数据则选中表头属性复选框
      if (count === selectedQuantity) {
        this.isPhysicalModelPropertiesCheckBoxDisabled = false
        this.isCheckPhysicalModelProperties = true
        this.indeterminatePhysicalModelProperties = false
        return
      }

      this.isPhysicalModelPropertiesCheckBoxDisabled = false
      this.indeterminatePhysicalModelProperties = true
      this.isCheckPhysicalModelProperties = false
    },

    /** 更新物模型功能复选框状态（表头） */
    updatePhysicalModelFunctionsCheckboxState() {
      const count = this.functions.length

      if (count <= 0) {
        this.isPhysicalModelFunctionsCheckBoxDisabled = true
        this.indeterminatePhysicalModelFunctions = false
        this.isCheckPhysicalModelFunctions = false
        return
      }

      let selectedQuantity = this.functions.filter(obj => obj.functionChecked === true).length

      // 没有选中的复选框则取消选中表头属性复选框
      if (selectedQuantity === 0) {
        this.isPhysicalModelFunctionsCheckBoxDisabled = false
        this.isCheckPhysicalModelFunctions = false
        this.indeterminatePhysicalModelFunctions = false
        return
      }

      // 总数量等于选中的数据则选中表头属性复选框
      if (count === selectedQuantity) {
        this.isPhysicalModelFunctionsCheckBoxDisabled = false
        this.isCheckPhysicalModelFunctions = true
        this.indeterminatePhysicalModelFunctions = false
        return
      }

      this.isPhysicalModelFunctionsCheckBoxDisabled = false
      this.indeterminatePhysicalModelFunctions = true
      this.isCheckPhysicalModelFunctions = false

    },

    /********************************* 复选框（表体） ***************************************/

    /** 选择单行产品数据时使用色块表示 */
    setProductCurrentRow(row) {
      this.$refs.productTable.setCurrentRow(row)
    },

    /** 选择单行设备数据时使用色块表示 */
    setDeviceCurrentRow(row) {
      this.$refs.deviceTable.setCurrentRow(row)
    },

    /** 产品列表选中事件 */
    async handleProductCurrentChangeEvent(data) {
      if (!data) return

      // 产品选中开始
      this.selectProductExecutionCallback = true

      // 缓存当前选中的产品信息
      this.currentSelectedProduct = data

      // 获取当前产品的设备数据
      await this.getDevices(data.id)

      // 选中设备表格第一行
      this.setDeviceCurrentRow(this.deviceList[0])

      if (this.invokeTarget.properties[data.id] && Object.keys(this.invokeTarget.properties[data.id]).length > 0) {
        // 还原选中的设备属性
        this.restoreCheckedDeviceProperties()
      } else {
        // 根据产品选中状态全选设备
        this.checkAllDeviceProperties(data.propertyChecked)
      }

      if (this.invokeTarget.functions[data.id] && Object.keys(this.invokeTarget.functions[data.id]).length > 0) {
        // 还原选中的设备功能
        this.restoreCheckedDeviceFunctions()
      } else {
        // 根据产品选中状态全选设备
        this.checkAllDeviceFunctions(data.functionChecked)
      }

      // 更新物模型属性复选框状态（表头）
      this.updatePhysicalModelPropertiesCheckboxState()

      // 更新物模型功能复选框状态（表头）
      this.updatePhysicalModelFunctionsCheckboxState()

      if (typeof this.selectProductExecutionCallback === 'function') {
        this.selectProductExecutionCallback()
      }

      this.selectProductExecutionCallback = false
    },

    /** 设备列表选中事件 */
    handleDeviceCurrentChangeEvent(data) {
      if (!data) return
      // 缓存当前选中的设备信息
      this.currentSelectedDevice = data

      this.properties = data.deriveMetadata.properties || []
      this.functions = data.deriveMetadata.functions || []

      if (this.invokeTarget.properties[data.productId]
        && this.invokeTarget.properties[data.productId][data.id]
        && Object.keys(this.invokeTarget.properties[data.productId][data.id]).length > 0) {
        this.restoreCheckedPhysicalModelProperties()
      } else {
        // 更新物模型属性复选框状态
        this.checkAllPhysicalModelProperties(data.propertyChecked)
      }

      if (this.invokeTarget.functions[data.productId]
        && this.invokeTarget.functions[data.productId][data.id]
        && Object.keys(this.invokeTarget.functions[data.productId][data.id]).length > 0) {
        this.restoreCheckedPhysicalModelFunctions()
      } else {
        // 更新物模型属性复选框状态
        this.checkAllPhysicalModelFunctions(data.functionChecked)
      }

    },

    /** 产品属性复选框选择变化事件处理 */
    handleCheckProductPropertyBoxChangeEvent(row) {

      const fun = () => {
        const productId = row.id
        const propertyChecked = row.propertyChecked

        // 如何产品下没有设备则不允许选中
        if (propertyChecked && this.deviceList.length <= 0) {
          this.$set(row, 'propertyChecked', false)
          return
        }

        // 更新产品属性绑定数据
        this.updateProductPropertiesInvokeTarget(productId, propertyChecked)
        // 全选设备属性
        this.checkAllDeviceProperties(propertyChecked)

        // 设置物模型属性为当前活跃标签
        this.activeName = 'properties'
      }

      if (this.selectProductExecutionCallback) {
        this.selectProductExecutionCallback = fun
      }else {
        fun()
      }

    },

    /** 产品功能复选框选择变化事件处理 */
    handleCheckProductFunctionBoxChangeEvent(row) {
      const fun = () => {
        const productId = row.id
        const functionChecked = row.functionChecked

        // 如何产品下没有设备则不允许选中
        if (functionChecked && this.deviceList.length <= 0) {
          this.$set(row, 'functionChecked', false)
          return
        }

        // 更新产品功能绑定数据
        this.updateProductFunctionsInvokeTarget(productId, functionChecked)
        // 全选设备功能
        this.checkAllDeviceFunctions(functionChecked)

        // 设置物模型功能为当前活跃标签
        this.activeName = 'functions'
      }

      if (this.selectProductExecutionCallback) {
        this.selectProductExecutionCallback = fun
      }else {
        fun()
      }
    },

    /** 设备属性复选框选择变化事件处理 */
    handleCheckDevicePropertyBoxChangeEvent(row) {
      const productId = row.productId
      const deviceId = row.id
      const propertyChecked = row.propertyChecked

      // 更新设备属性绑定数据
      this.updateDevicePropertiesInvokeTarget(productId, deviceId, propertyChecked, row.deriveMetadata)
      // 更新设备属性复选框状态（表头）
      this.updateDevicePropertiesCheckboxState()
      // 更新物模型属性复选框状态
      this.checkAllPhysicalModelProperties(propertyChecked)
      // 设置物模型属性为当前活跃标签
      this.activeName = 'properties'
    },

    /** 设备功能复选框选择变化事件处理 */
    handleCheckDeviceFunctionBoxChangeEvent(row) {
      const productId = row.productId
      const deviceId = row.id
      const functionChecked = row.functionChecked

      // 更新设备属性绑定数据
      this.updateDeviceFunctionsInvokeTarget(productId, deviceId, functionChecked, row.deriveMetadata)
      // 更新设备功能复选框状态（表头）
      this.updateDeviceFunctionsCheckboxState()
      // 更新物模型功能复选框状态
      this.checkAllPhysicalModelFunctions(functionChecked)
      // 设置物模型功能为当前活跃标签
      this.activeName = 'functions'
    },

    /** 物模型属性复选框选择变化事件处理 */
    handleCheckPhysicalModelPropertyBoxChangeEvent(row) {
      const productId = this.currentSelectedProduct.id
      const deviceId = this.currentSelectedDevice.id
      const propertyId = row.id
      const propertyChecked = row.propertyChecked

      // 更新物模型属性绑定数据
      this.updatePhysicalModelPropertiesInvokeTarget(productId, deviceId, propertyId, propertyChecked)
      // 更新物模型属性复选框状态（表头）
      this.updatePhysicalModelPropertiesCheckboxState()
    },

    /** 物模型功能复选框选择变化事件处理 */
    handleCheckPhysicalModelFunctionBoxChangeEvent(row) {
      const productId = this.currentSelectedProduct.id
      const deviceId = this.currentSelectedDevice.id
      const functionId = row.id
      const functionChecked = row.functionChecked

      // 更新物模型功能绑定数据
      this.updatePhysicalModelFunctionsInvokeTarget(productId, deviceId, functionId, functionChecked)
      // 更新物模型功能复选框状态（表头）
      this.updatePhysicalModelFunctionsCheckboxState()
    },

    /** 全选设备属性 */
    checkAllDeviceProperties(state) {
      // 级联选择设备
      this.deviceList.forEach(device => {
        if (device.haveProperty) {
          this.$set(device, 'propertyChecked', state)
          // 更新设备属性绑定数据
          this.updateDevicePropertiesInvokeTarget(device.productId, device.id, state, device.deriveMetadata)
          // 更新选中的的设备物模型属性
          if (device.id === this.currentSelectedDevice.id) {
            this.checkAllPhysicalModelProperties(state)
          }
        }
      })
      // 更新设备属性复选框状态
      this.updateDevicePropertiesCheckboxState()
    },

    /** 全选设备功能 */
    checkAllDeviceFunctions(state) {
      this.deviceList.forEach(device => {
        if (device.haveFunction) {
          this.$set(device, 'functionChecked', state)
          // 更新设备功能绑定数据
          this.updateDeviceFunctionsInvokeTarget(device.productId, device.id, state, device.deriveMetadata)
          // 更新选中的的设备物模型功能
          if (device.id === this.currentSelectedDevice.id) {
            this.checkAllPhysicalModelFunctions(state)
          }
        }
      })

      // 更新设备功能复选框状态
      this.updateDeviceFunctionsCheckboxState()
    },

    /** 全选物模型属性 */
    checkAllPhysicalModelProperties(state) {
      this.properties.forEach(property => {
        this.$set(property, 'propertyChecked', state)
        // 更新物模型属性绑定数据
        this.updatePhysicalModelPropertiesInvokeTarget(
          this.currentSelectedDevice.productId,
          this.currentSelectedDevice.id,
          property.id,
          state)
      })

      // 更新物模型属性复选框状态
      this.updatePhysicalModelPropertiesCheckboxState()
    },

    /** 全选物模型功能 */
    checkAllPhysicalModelFunctions(state) {
      // 级联选择设备
      this.functions.forEach(fun => {
        this.$set(fun, 'functionChecked', state)
        // 更新物模型功能绑定数据
        this.updatePhysicalModelFunctionsInvokeTarget(
          this.currentSelectedDevice.productId,
          this.currentSelectedDevice.id,
          fun.id,
          state)
      })

      // 更新物模型功能复选框状态
      this.updatePhysicalModelFunctionsCheckboxState()
    },

    /** 还原选中的产品属性 */
    restoreCheckedProductProperties() {
      this.productList.forEach(product => {
        this.$set(product, 'propertyChecked', !!this.invokeTarget.properties[product.id])
      })
    },

    /** 还原选中的产品功能 */
    restoreCheckedProductFunctions() {
      this.productList.forEach(product => {
        this.$set(product, 'functionChecked', !!this.invokeTarget.functions[product.id])
      })
    },

    /** 还原选中的设备属性 */
    restoreCheckedDeviceProperties() {
      const checkedDevice = this.invokeTarget.properties[this.currentSelectedProduct.id] || {}

      this.deviceList.forEach(device => {
        this.$set(device, 'propertyChecked', !!checkedDevice[device.id] && device.haveProperty)
      })

      // 更新设备功能复选框状态
      this.updateDevicePropertiesCheckboxState()
    },

    /** 还原选中的设备功能 */
    restoreCheckedDeviceFunctions() {

      const checkedDevice = this.invokeTarget.functions[this.currentSelectedProduct.id] || {}

      this.deviceList.forEach(device => {
        this.$set(device, 'functionChecked', !!checkedDevice[device.id] && device.haveFunction)
      })

      // 更新设备功能复选框状态
      this.updateDeviceFunctionsCheckboxState()
    },

    /** 还原选中的物模型属性 */
    restoreCheckedPhysicalModelProperties() {
      const checkedDevice = this.invokeTarget.properties[this.currentSelectedProduct.id]
      if (!checkedDevice) {
        return
      }
      const checkedProperties = checkedDevice[this.currentSelectedDevice.id]
      if (!checkedProperties) {
        return
      }

      this.properties.forEach(property => {
        this.$set(property, 'propertyChecked', !!checkedProperties[property.id])
      })

      // 更新物模型属性复选框状态（表头）
      this.updatePhysicalModelPropertiesCheckboxState()

    },

    /** 还原选中的物模型功能 */
    restoreCheckedPhysicalModelFunctions() {
      const checkedDevice = this.invokeTarget.functions[this.currentSelectedProduct.id]
      if (!checkedDevice) {
        return
      }
      const checkedFunctions = checkedDevice[this.currentSelectedDevice.id]
      if (!checkedFunctions) {
        return
      }

      this.functions.forEach(fun => {
        this.$set(fun, 'functionChecked', !!checkedFunctions[fun.id])
      })

      // 更新物模型功能复选框状态（表头）
      this.updatePhysicalModelFunctionsCheckboxState()
    },

    /********************************* 数据绑定 ***************************************/

    /** 更新产品属性绑定数据 */
    updateProductPropertiesInvokeTarget(productId, propertyChecked) {
      if (propertyChecked && !this.invokeTarget.properties[productId]) {
        // 将产品信息添加到绑定
        this.invokeTarget.properties[productId] = {}
      }else if (!propertyChecked && this.invokeTarget.properties[productId]) {
        // 将产品信息解除绑定
        delete this.invokeTarget.properties[productId]
      }
    },

    /** 更新产品功能绑定数据 */
    updateProductFunctionsInvokeTarget(productId, functionChecked) {
      if (functionChecked && !this.invokeTarget.functions[productId]) {
        // 将产品信息添加到绑定
        this.invokeTarget.functions[productId] = {}
      }else if (!functionChecked && this.invokeTarget.functions[productId]) {
        // 将产品信息解除绑定
        delete this.invokeTarget.functions[productId]
      }
    },

    /** 更新设备属性绑定数据 */
    updateDevicePropertiesInvokeTarget(productId, deviceId, propertyChecked, metadata) {
      if (propertyChecked) {
        if (!this.invokeTarget.properties[productId]) {
          this.invokeTarget.properties[productId] = {}
        }

        if (!this.invokeTarget.properties[productId][deviceId]) {
          this.invokeTarget.properties[productId][deviceId] = {}
        }

        if (metadata) {
          metadata.properties.forEach(property => {
            // 更新物模型属性绑定数据
            this.updatePhysicalModelPropertiesInvokeTarget(productId, deviceId, property.id, propertyChecked)
          })
        }

      } else {
        if (this.invokeTarget.properties[productId] && this.invokeTarget.properties[productId][deviceId]) {
          delete this.invokeTarget.properties[productId][deviceId]
        }
      }

    },

    /** 更新设备功能绑定数据 */
    updateDeviceFunctionsInvokeTarget(productId, deviceId, functionChecked, metadata) {
      if (functionChecked) {
        if (!this.invokeTarget.functions[productId]) {
          this.invokeTarget.functions[productId] = {}
        }

        if (!this.invokeTarget.functions[productId][deviceId]) {
          this.invokeTarget.functions[productId][deviceId] = {}
        }

        if (metadata) {
          metadata.functions.forEach(fun => {
            // 更新物模型属性绑定数据
            this.updatePhysicalModelFunctionsInvokeTarget(productId, deviceId, fun.id, functionChecked)
          })
        }

      } else {
        if (this.invokeTarget.functions[productId] && this.invokeTarget.functions[productId][deviceId]) {
          delete this.invokeTarget.functions[productId][deviceId]
        }
      }

    },

    /** 更新物模型属性绑定数据 */
    updatePhysicalModelPropertiesInvokeTarget(productId, deviceId, propertyId, propertyChecked) {
      if (propertyChecked) {
        if (!this.invokeTarget.properties[productId]) {
          this.invokeTarget.properties[productId] = {}
        }

        if (!this.invokeTarget.properties[productId][deviceId]) {
          this.invokeTarget.properties[productId][deviceId] = {}
        }

        if (!this.invokeTarget.properties[productId][deviceId][propertyId]) {
          this.invokeTarget.properties[productId][deviceId][propertyId] = {
            sendAndForget: true,
            // 不记录此消息到日志
            ignoreLog: true,
            // 类型有 get 获取属性操作；set 设置属性操作， 类型为set 必须设置值（value: ）
            type: 'get',
            // value: ''
          }
        }

        return
      }

      if (this.invokeTarget.properties[productId]
        && this.invokeTarget.properties[productId][deviceId]
        && this.invokeTarget.properties[productId][deviceId][propertyId]) {
        delete this.invokeTarget.properties[productId][deviceId][propertyId]
      }

    },

    /** 更新物模型功能绑定数据 */
    updatePhysicalModelFunctionsInvokeTarget(productId, deviceId, functionId, functionChecked) {
      if (functionChecked) {
        if (!this.invokeTarget.functions[productId]) {
          this.invokeTarget.functions[productId] = {}
        }

        if (!this.invokeTarget.functions[productId][deviceId]) {
          this.invokeTarget.functions[productId][deviceId] = {}
        }

        if (!this.invokeTarget.functions[productId][deviceId][functionId]) {
          this.invokeTarget.functions[productId][deviceId][functionId] = {
            sendAndForget: true,
            // 不记录此消息到日志
            ignoreLog: true,
            inputs: {}
          }
        }

        return
      }

      if (this.invokeTarget.functions[productId]
        && this.invokeTarget.functions[productId][deviceId]
        && this.invokeTarget.functions[productId][deviceId][functionId]) {
        delete this.invokeTarget.functions[productId][deviceId][functionId]
      }
    },

  }
}
</script>

<style lang="scss" scoped>

.el-table ::v-deep .label-properties .cell:before {
  content: "属性";
  position: relative;
  right: 5px;
}

.el-table ::v-deep .label-functions .cell:before {
  content: "功能";
  position: relative;
  right: 5px;
}

</style>
